package com.pan.structual.proxy;

import com.pan.structual.proxy.target.Common;
import com.pan.structual.proxy.target.Hello;
import com.pan.structual.proxy.target.proxy.HelloProxy;
import com.pan.structual.proxy.target.proxy.HelloProxy2;

import java.lang.reflect.Proxy;


/**
 *  代理模式
 *代理模式作为一种常用的设计模式，它的优点具体如下：
 *
 * 分离关注点：代理模式能够将代理对象与真实被调用的目标对象分离，这样做有助于将不同的关注点分离开，使得系统更加模块化。
 * 降低耦合度：通过引入代理对象，客户端与目标对象之间的直接依赖被去除，从而在一定程度上降低了系统的耦合度，提高了扩展性。
 * 保护目标对象：代理模式可以在客户端和目标对象之间起到一个中介的作用，保护目标对象不被直接访问，从而可以控制对目标对象的访问权限。
 * 功能增强：代理类可以在不改变目标对象的基础上增加额外的功能，如日志记录、权限检查等，这样可以在不影响原有业务逻辑的情况下对目标对象的功能进行增强。
 * 然而，代理模式也有一些缺点需要考虑：
 *
 * 增加系统复杂度：引入代理对象会增加系统中类的总数，这可能会使得系统的设计变得更加复杂，对于初学者来说可能不容易理解。
 * 性能开销：每次客户端请求都需要通过代理对象，这可能会引入一定的性能开销，尤其是在高频调用的场景下，这种开销可能会变得明显。
 * 代码维护：由于引入了额外的代理类，这意味着需要额外的代码来维护这些类，这可能会增加开发和维护的工作量。
 *
 * 总的来说，在实际使用中，代理模式适用于那些需要控制对对象访问、增强对象功能或者降低系统耦合度的场景。
 * 在设计系统时，应当权衡代理模式带来的优势和潜在的复杂性及性能影响，以决定是否采用该模式。
 *
 */
public class ProxyApplication {
    public static void main(String[] args) {
        System.out.println("代理1：");
        Common hello = new Hello();
        hello = new HelloProxy(hello);
        hello.use();

        System.out.println("\n\n代理2：");
        hello = (Common) Proxy.newProxyInstance(
                ClassLoader.getSystemClassLoader(),
                hello.getClass().getInterfaces(),
                new HelloProxy2(hello));
        hello.use();


        System.out.println("\n\n代理3：");
        hello = new HelloProxy(hello);
        hello.use();


        System.out.println("\n\n代理4：");
        hello = (Common) Proxy.newProxyInstance(
                ClassLoader.getSystemClassLoader(),
                hello.getClass().getInterfaces(),
                new HelloProxy2(hello));
        hello.use();

    }
}
